import type { Ref } from 'react';
import React, { useCallback, useState, useEffect, forwardRef } from 'react';
import { Icon, EditStatus } from 'gantd';
import classnames from 'classnames';
import Zmage from 'react-zmage';
import { Tooltip, Modal, message } from 'antd';
import { isEqual, isString } from 'lodash';
import { getImageByPreviewId } from '@/utils/utils';
import ImageSelector from './ImageSelector';
import styles from './index.less';
import request from '@/utils/request';

interface Image {
  id: string;
  virtureId: string;
}

interface RenderImage extends Image {
  src?: string;
}

interface Props {
  placeholder: React.ReactNode | string | null;
  maxLength: number;
  value: Image[];
  onChange: (value: Image[]) => void;
  edit: EditStatus;
  allowDelete: boolean;
}

// 建立图片真实id与图片信息的仓库
const imageHouse = new Map<string, Image>();
const querying = new Set(); // 正在请求

// 缓存数组默认值
const cacheValueInit: RenderImage[] = [];
const initialValue = [] as Image[];
/**
 *
 *
 * @value array `value`表示图片数组，每一个图片对象包含`virtureId`字段,用以获取图片
 * @onChange function 上传或删除之后的回调
 * @maxLength 图片数量最大值，超过以后不显示上传按钮
 * @edit 是否处于编辑状态，默认false,不会显示上传按钮，保存的时候传0,才会去调取删除图片的接口
 * @allowDelete 是否显示删除按钮
 */
const Upload = (props: Props, ref: Ref<any>) => {
  const {
    value = initialValue,
    maxLength = 5,
    onChange = () => {},
    edit = EditStatus.CANCEL,
    allowDelete = true,
    placeholder = <span style={{ color: '#ccc' }}>{tr('暂无图片')}</span>,
  } = props;

  if (!Number.isInteger(maxLength) || maxLength < 0) {
    throw new Error('maxLength' + tr('必须是大于0的整数'));
  }

  const [queryCount, setqueryCount] = useState(0);

  const queryImageInfo = useCallback((ids: string[]) => {
    // 避免重复请求
    const key = ids.join(',');
    if (querying.has(key)) return;
    querying.add(key);
    request
      .post('/gmetaBiz/getFileAndPictureInfo', {
        data: {
          ids,
        },
      })
      .then((data: Image[]) => {
        ids.forEach((id) => {
          const item = data.find((item) => item.id === id);
          if (item) {
            // 文件还存在
            imageHouse.set(id, item);
          } else {
            imageHouse.set(id, { virtureId: '-1' } as Image);
          }
        });
        setqueryCount((count) => count + 1);
        querying.delete(key);
      });
  }, []);

  const getImages = useCallback(() => {
    const imgs = value.slice(0, maxLength);
    // 过滤掉不存在的文件
    const imgObjs = imgs
      .filter((item) => !isString(item) && item.virtureId !== '-1')
      .map((item: RenderImage) => {
        if (item.src) return item;
        if (item.virtureId) return { ...item, src: getImageByPreviewId(item.virtureId) };
        if (item.id) {
          const imgobj = imageHouse.get(item.id);
          if (imgobj) {
            const { virtureId } = imgobj;
            if (virtureId) return { ...item, virtureId, src: getImageByPreviewId(virtureId) };
          }
        }
        return item;
      });
    // 过滤出正式文件，获取临时id
    const ids = imgObjs.filter((item: RenderImage) => !item.src && !item.virtureId && item.id);
    if (ids.length) {
      queryImageInfo(ids.map((item: RenderImage) => item.id) as string[]);
    }
    return imgObjs;
  }, [value]);

  const [images, setImages] = useState(getImages);
  const [previewIndex, setPreviewIndex] = useState(0);
  const [zmage, setZmage] = useState({ setState: (param: any) => {} });
  const [modal, setModal] = useState();
  const [deleting, setDeleting] = useState(false);

  const [cacheValue, setcacheValue] = useState(images);
  const [deleteImages, setdeleteImages] = useState(cacheValueInit);

  // 修改图片
  const modifyImages = useCallback(
    (list: RenderImage[]) => {
      if (!isEqual(list, images)) {
        setImages(list);
        onChange(list);
      }
    },
    [images],
  );
  // 调用删除接口
  const deleteAction = useCallback(() => {
    if (!deleteImages.length) return;
    request.post('/file/remove', {
      data: {
        ids: deleteImages.map((img) => img.virtureId),
      },
    });
  }, [deleteImages]);

  // 图片改变手动更新一次
  useEffect(() => {
    setImages(getImages());
  }, [value]);

  useEffect(() => {
    modifyImages(getImages());
  }, [queryCount]);

  // 编辑状态改变
  useEffect(() => {
    if (edit === EditStatus.EDIT) {
      // 进入编辑状态，要缓存
      setcacheValue(images);
    } else if (edit === EditStatus.SAVE) {
      // 保存
      setcacheValue(cacheValueInit);
      deleteAction();
    } else {
      // 取消编辑，重置value
      setcacheValue(cacheValueInit);
      setdeleteImages(cacheValueInit);
      modifyImages(cacheValue);
    }
  }, [edit]);

  // 预览
  const preview = useCallback(
    (index) => {
      setPreviewIndex(index);
      zmage.setState({
        browsing: true,
      });
    },
    [zmage],
  );

  useEffect(() => {
    if (modal) {
      modal.update({
        okButtonProps: {
          loading: deleting,
        },
      });
    }
  }, [deleting]);

  // 删除
  const remove = useCallback(
    (index) => {
      const deleteModal = Modal.warning({
        title: tr('提示'),
        content: `${tr('是否确认删除')}`,
        okText: tr('确认'),
        okType: 'danger',
        cancelText: tr('取消'),
        onOk(cb) {
          setDeleting(true);
          const copyList = [...images];
          const deleted = copyList.splice(index, 1)[0];

          setdeleteImages((d) => {
            d.push(deleted);
            return d;
          });
          modifyImages(copyList);
          setDeleting(true);
          message.success(tr('删除成功'));
          cb();
        },
      });
      setModal(() => deleteModal);
    },
    [images],
  );

  const onConfirm = useCallback(
    (image: Image) => {
      const item = { ...image, src: getImageByPreviewId(image.virtureId) };
      const newList: RenderImage[] = [...images, item];
      modifyImages(newList);
    },
    [images],
  );

  const onZmage = useCallback((zg: any) => {
    if (zg) {
      setZmage(zg);
    }
  }, []);

  if (edit !== EditStatus.EDIT && images.length <= 0) {
    return placeholder;
  }

  return (
    <div className={styles.upload} ref={ref}>
      {images.map((img: RenderImage, index) => (
        <div
          className={styles['upload-list-item']}
          style={{ backgroundImage: `url(${img.src})` }}
          key={img.virtureId || img.id}
        >
          <div className={styles['upload-list-item-tools']}>
            <Tooltip title={tr('预览')}>
              <Icon.Ant type="eye" className={styles['upload-list-item-icon']} onClick={() => preview(index)} />
            </Tooltip>
            {edit === EditStatus.EDIT && allowDelete ? (
              <Tooltip title={tr('删除')}>
                <Icon.Ant type="delete" className={styles['upload-list-item-icon']} onClick={() => remove(index)} />
              </Tooltip>
            ) : null}
          </div>
        </div>
      ))}
      {images.length < maxLength && edit === EditStatus.EDIT ? (
        <ImageSelector onConfirm={onConfirm}>
          <div className={classnames(styles['upload-block'], styles['upload-list-item'])}>
            <Icon.Ant type="cloud-upload" />
          </div>
        </ImageSelector>
      ) : null}
      <Zmage style={{ width: 0 }} ref={onZmage} set={images} defaultPage={previewIndex} />
    </div>
  );
};

export default forwardRef(Upload);
